package utils

import (
    "strings"
    "sync"
    "time"
    "github.com/beego/beego/v2/core/logs"
    "github.com/beego/beego/v2/server/web"
    "fmt"
)

var (
    etcdClientOnce sync.Once
    etcdClient     *EtcdClient
)

// InitClients 初始化所有客户端
func InitClients() error {
    // 使用 spdk_client.go 提供的 GetSPDKClient，无需重复赋值
    if GetSPDKClient() == nil {
        return fmt.Errorf("failed to initialize SPDK client")
    }

    // 初始化ETCD客户端
    if err := initEtcdClient(); err != nil {
        return err
    }
    
    return nil
}

func initEtcdClient() error {
    var err error
    retryTimes := web.AppConfig.DefaultInt("etcd::retry_times", 3)
    retryInterval := web.AppConfig.DefaultInt("etcd::retry_interval", 2)

    endpoints, _ := web.AppConfig.String("etcd::endpoints")
    username, _ := web.AppConfig.String("etcd::username")
    password, _ := web.AppConfig.String("etcd::password")

    logs.Info("[ETCD] Starting connection attempts to cluster")

    for i := 0; i < retryTimes; i++ {
        logs.Info("=========================================")
        logs.Info("[ETCD] Connection attempt %d/%d", i+1, retryTimes)
        logs.Info("[ETCD] Target endpoints: %s", endpoints)
        
        etcdClientOnce.Do(func() {
            etcdClient, err = NewEtcdClient(
                strings.Split(endpoints, ","),
                username,
                password,
            )
        })

        if err == nil && etcdClient != nil {
            if _, testErr := etcdClient.Get("/health_check"); testErr == nil {
                logs.Info("[ETCD] Successfully connected to cluster")
                logs.Info("=========================================")
                return nil
            } else {
                logs.Error("[ETCD] Connection test failed: %v", testErr)
                err = testErr
            }
        }

        if i < retryTimes-1 {
            logs.Error("[ETCD] Connection failed, will retry in %d seconds", retryInterval)
            logs.Error("[ETCD] Error details: %v", err)
            logs.Info("=========================================")
        } else {
            logs.Critical("[ETCD] All connection attempts failed")
            logs.Critical("[ETCD] Final error: %v", err)
            logs.Info("=========================================")
        }
        
        time.Sleep(time.Duration(retryInterval) * time.Second)
        etcdClientOnce = sync.Once{}
    }

    return fmt.Errorf("failed to connect to etcd after %d attempts", retryTimes)
}

// GetEtcdClient 获取ETCD客户端实例
func GetEtcdClient() *EtcdClient {
    if etcdClient == nil {
        if err := initEtcdClient(); err != nil {
            logs.Error("Failed to initialize ETCD client: %v", err)
            return nil
        }
    }
    return etcdClient
}

// CloseClients 关闭所有客户端连接
func CloseClients() {
    if etcdClient != nil {
        etcdClient.Close()
    }
}

// CheckEtcdConnection 检查etcd连接是否可用
func CheckEtcdConnection(client *EtcdClient) bool {
    if client == nil {
        logs.Error("[ETCD] Client is not initialized")
        return false
    }
    
    start := time.Now()
    _, err := client.Get("/health_check")
    elapsed := time.Since(start)
    
    if err != nil {
        logs.Error("[ETCD] Connection check failed (latency: %v)", elapsed)
        logs.Error("[ETCD] Error: %v", err)
        return false
    }
    
    logs.Info("[ETCD] Connection check successful (latency: %v)", elapsed)
    return true
}

// WaitForEtcdConnection 等待etcd连接就绪
func WaitForEtcdConnection(maxRetries int, retryInterval int) (*EtcdClient, error) {
    for i := 0; i < maxRetries; i++ {
        client := GetEtcdClient()
        if client != nil && CheckEtcdConnection(client) {
            return client, nil
        }
        
        if i < maxRetries-1 {
            logs.Warning("Waiting for etcd connection, retry %d/%d", i+1, maxRetries)
            time.Sleep(time.Duration(retryInterval) * time.Second)
        }
    }
    return nil, fmt.Errorf("failed to establish stable connection to etcd after %d retries", maxRetries)
}
